#include "core.h"
#include "ServerCore.h"
#include "GlobalConfig.h"
#include "NetMgr.h"
#include <google/protobuf/message.h>
#include "PacketProcessor.h"
#include "xMsgHandler.h"
#include "ComputureMgr.h"
#include "DBMgr.h"
#include "UserMgr.h"
#include "RoleMgr.h"
//------------------------------------------------------------------------------------------------------
xBase::xBase(CGuidMgr::_eEntityType et/* = CGuidMgr::ENTITY_NONE */, U64 uGuid /* = 0 */)
: m_eEntityType(et)
, m_uuGuid(uGuid)
, m_uBindGuid(0)
{
	if(m_uuGuid == 0)
	{
		m_uuGuid = CGuidMgr::getInstance()->GenGUID(et);
	}
}
xBase::~xBase()
{
	
}

void xBase::onUnBind()
{

}
//------------------------------------------------------------------------------------------------------
boost::unordered_map<U64, xObjBase*>	xObjBase::m_mapObjMgr;

xObjBase::xObjBase(CGuidMgr::_eEntityType et, U64 uGuid)
: xBase(et, uGuid)
{
	if(m_uuGuid == 0)
	{
		m_uuGuid = CGuidMgr::getInstance()->GenGUID(et);
	}
	addObj(m_uuGuid, this);
}

xObjBase::~xObjBase()
{
	delObj(m_uuGuid);
}

xObjBase* xObjBase::getObj(U64 uGuid)
{
	boost::unordered_map<U64, xObjBase*>::iterator it = m_mapObjMgr.find(uGuid);
	if (it != m_mapObjMgr.end())
	{
		return it->second;
	}

	return NULL;
}

BOOL xObjBase::addObj(U64 uGuid, xObjBase* pObj)
{
	std::pair<boost::unordered_map<U64, xObjBase*>::iterator, bool> ins = 
		m_mapObjMgr.insert(std::pair<U64, xObjBase*>(uGuid, pObj));
	return ins.second ? TRUE : FALSE;
}

BOOL xObjBase::delObj(U64 uGuid)
{
	boost::unordered_map<U64, xObjBase*>::iterator it = m_mapObjMgr.find(uGuid);
	if (it != m_mapObjMgr.end())
	{
		xObjBase* pO = it->second;
		if (pO->m_uBindGuid)
		{
			pO->onUnBind();
		}

		m_mapObjMgr.erase(it);
		return TRUE;
	}
	return FALSE;
}

void xObjBase::onUnBind()
{
	UnBind();
}
//------------------------------------------------------------------------------------------------------
boost::unordered_map<U64, net_obj_ptr>	xNetObjBase::m_mapNetObjMgr;
CWnLock									xNetObjBase::m_lock;

xNetObjBase::xNetObjBase(CGuidMgr::_eEntityType et/* = CGuidMgr::ENTITY_NONE */, U64 uGuid /* = 0 */)
: xBase(et, uGuid)
{

}

xNetObjBase::~xNetObjBase()
{
	delNetObj(m_uuGuid);
}

void xNetObjBase::onUnBind()
{
	MYTH::ObjDleParameter objdel;
	objdel.set_bind_guid(m_uBindGuid);
	xMSG msg(MYTH::CMD_Obj_Del, &objdel);
	msg.call_guid = m_uuGuid;
	CPacketProcesser::getInstance()->MsgIn(msg);

	UnBind();
}
//------------------------------------------------------------------------------------------------------
IMP_SINGLETON_CLASS(CServerCore);

CServerCore::CServerCore()
: handler(NULL)
{
	 
}

CServerCore::~CServerCore()
{
	
}

void CServerCore::SendMsg2Server(std::string& ip_port, xMSG& msg)
{
	CComputureMgr* pCMgr = CComputureMgr::getInstance();
	if (pCMgr)
	{
		pCMgr->SendMsg2Server(ip_port, msg);
	}
}

void CServerCore::SendMsg2Server(ENetDef::_eNet et, xMSG& msg)
{
	CComputureMgr* pCMgr = CComputureMgr::getInstance();
	if (pCMgr)
	{
		pCMgr->SendMsg2Server(et, msg);
	}
}

void CServerCore::SendMsg2Logic(U64 uGuid, xMSG& msg)
{
	xObjBase* pL = xObjBase::getObj(uGuid);
	if (pL)
	{
		return SendMsg2Net(pL->getBindGuid(), msg);
	}
}

void CServerCore::SendMsg2Net(U64 uGuid, xMSG& msg)
{
	net_obj_ptr pN = xNetObjBase::getNetObj(uGuid);
	if (pN.get())
	{
		CAsioTcpLink* pLink = dynamic_cast<CAsioTcpLink*>(pN.get());
		if (pLink)
		{
			pLink->prepWrite(msg.msg_ptr, msg.dwLen);
		}
	}
}

S32 CServerCore::newTcpClient( ENetDef::_eNet remote_card, std::string remote_ip, U16 remote_port )
{
	CCfgNet * cfg_net = CClobalConfigMgr::getInstance()->mpCfgNet;
	CNetMgr * net_mgr = CNetMgr::getInstance();

	itemHMapTcpClientLocal index = cfg_net->mpCurServer->tcp_client_locals.find( remote_card );
	if ( index != cfg_net->mpCurServer->tcp_client_locals.end() )
	{
		return net_mgr->addNetClient( remote_card, index->second.local_card, 
			index->second.local_ip, index->second.local_port, 
			remote_ip, remote_port );
	}
	return -1;
}

void CServerCore::startNet()
{
	CCfgNet * cfg_net = CClobalConfigMgr::getInstance()->mpCfgNet;
	CNetMgr * net_mgr = CNetMgr::getInstance();
	// tcp server
	itemHMapTcpServer itemTcpServer = cfg_net->mpCurServer->tcp_servers.begin();
	for ( ; itemTcpServer != cfg_net->mpCurServer->tcp_servers.end(); itemTcpServer++ )
	{
		net_mgr->addNetServer(itemTcpServer->second.local_ip,
			itemTcpServer->second.local_port,
			itemTcpServer->second.local_card);
	}
	// tcp client
	itemHMapTcpClient itemTcpClient = cfg_net->mpCurServer->tcp_clients.begin();
	for ( ; itemTcpClient != cfg_net->mpCurServer->tcp_clients.end(); itemTcpClient++ )
	{
		newTcpClient( itemTcpClient->second.remote_card, itemTcpClient->second.remote_ip,
			itemTcpClient->second.remote_port );
	}
}

void CServerCore::LoadDB()
{
	CCfgDb * cfg_db = CClobalConfigMgr::getInstance()->mpCfgDb;
	if ( NULL!=cfg_db )
	{
		CDBMgr::createInstance();
		CDBMgr* pDBMgr = CDBMgr::getInstance();
		itemDbCfg index=cfg_db->mDBs.find("db_info");
		if ( index!=cfg_db->mDBs.end() )
		{
			pDBMgr->init( index->second.connect_count,
				index->second.name,
				index->second.ip, 
				index->second.port,
				index->second.user_name, 
				index->second.password );
		}
	}
}

BOOL CServerCore::ConConstruct()
{
	CClobalConfigMgr::createInstance();
	CServerCore::createInstance();
	CNetMgr::createInstance();
	CPacketProcesser::createInstance();
	CGuidMgr::createInstance();
	CComputureMgr::createInstance();
	CUserMgr::createInstance();
	CRoleMgr::createInstance();

	CPacketProcesser::getInstance()->start();

	if(!handler)
	{
		handler = new CMsgHandler();
	}

	return TRUE;
}

void CServerCore::Terminal()
{
	if (handler)
	{
		delete handler;
		handler = NULL;
	}

	CUserMgr::destroyInstance();
	CRoleMgr::destroyInstance();
	CClobalConfigMgr::destroyInstance();
	CNetMgr::destroyInstance();
	CPacketProcesser::destroyInstance();
	CGuidMgr::destroyInstance();
	CComputureMgr::destroyInstance();
}